package locality;

import java.util.ArrayList;

import mantel.mantelTest;

import tool.*;

import genome.*;

public class distanceMapGenerator {
	public ReverseHashTable<Genotype,ArrayList<Integer>> genotypeToPhenotype = new ReverseHashTable<Genotype,ArrayList<Integer>>();
	public ReverseHashTable<ArrayList<Integer>,Genotype> phenotypeToGenotype = new ReverseHashTable<ArrayList<Integer>,Genotype>();
	
	public static void main(String args[]){
		
		distanceMapGenerator dmg = new distanceMapGenerator();
		double[] in = {0.0,0.0};
		int size = 3;
		
		//GGT g = new GGT(in,size,1,2);
		BG g = new BG(size);
		dmg.populateHashTable(g);
		System.out.println(dmg.genotypeToPhenotype);
		
		ArrayList<double[][]> dmat = dmg.genDMatrix();
		double[][] X = dmat.get(0);
		double[][] Y = dmat.get(1);
		Utility.printMat(X); System.out.println();
		Utility.printMat(Y); System.out.println();
		
		double[] test = mantelTest.mantel(X, Y, 1000,false);
		System.out.println("Mantel Correlation: "+test[0]+" "+" Significance: "+test[1]);
		double[][] cor = mantelTest.segmented_mantel_cor(X, Y, 1000,1,size);
		mantelTest.printCorrelog(cor);
		
		
	}
	
	public void populateHashTable(Genotype g){
		
		//Obtains the genotype space for input genotype, then generates the corresponding vector for each member and adds both to the hashtable
		ArrayList<Genotype> space = g.generateSpace();
		for(Genotype individual:space){
			ArrayList<Integer> phenotype = new ArrayList<Integer>();
			int[] x = individual.toVector();
			for(int i=0;i<x.length;i++){
				phenotype.add(x[i]);
			}
			genotypeToPhenotype.put(individual,phenotype);
		}
		
		phenotypeToGenotype = genotypeToPhenotype.getInverse(); //also create inverse map
	}
	
	public ArrayList<double[][]> genDMatrix(){
		//naive approach first - maybe include distance matrix class for more efficient routines later
		
		ArrayList<double[][]> dmatrices = new ArrayList<double[][]>();
		
		int x = genotypeToPhenotype.size();
		double[][] GDIFF = new double[x][x];
		double[][] PDIFF = new double[x][x];
		
		ArrayList<Genotype> gspace = new ArrayList<Genotype>(genotypeToPhenotype.keySet());
		int i=0; int j=0;
		for(Genotype g1:gspace){
			for(Genotype g2:gspace){
				GDIFF[i][j] = g1.diff(g2);
				
				ArrayList<Integer> p1 = genotypeToPhenotype.get(g1);
				ArrayList<Integer> p2 = genotypeToPhenotype.get(g2);
				PDIFF[i][j] = euclid(p1,p2);
				j = j+1;
			}
			j = 0;
			i = i+1;
		}
		dmatrices.add(GDIFF); dmatrices.add(PDIFF);
		return dmatrices;
	}
	
	public static double euclid(ArrayList<Integer> i1, ArrayList<Integer> i2){
		//returns the euclidean distance between two integer arrays
		double e2 = 0.0;
		for(Integer x1:i1){
			for(Integer x2:i2){
				e2 = e2+ Math.pow((x2-x1),2);
			}
		}
		return Math.sqrt(e2);
	}
	
}
